# 实现一个简单的orm
import numbers

class Field:
    pass

class IntegerField(Field):
    def __init__(self, db_column, min_value=None, max_value=None):
        self._value = None
        self.min_value = min_value
        self.max_value = max_value
        self.db_column = db_column
        if min_value is not None:
            if not isinstance(min_value, numbers.Integral):
                raise ValueError('min_value must be int')
            if min_value < 0:
                raise ValueError('min_value must be positive int')
        if max_value is not None:
            if not isinstance(max_value, numbers.Integral):
                raise ValueError('max_value must be int')
            if min_value < 0:
                raise ValueError('max_value must be positive int')
        if max_value is not None and min_value is not None:
            if min_value > max_value:
                raise ValueError('min_value must smaller then max_value')

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        if not isinstance(value,numbers.Integral):
            raise ValueError('int value need')
        if value < 0:
            raise ValueError('value must positive')
        if value < self.min_value or value > self.max_value:
            raise ValueError('value must between min_value and max_value')
        self._value = value


class CharField(Field):
    def __init__(self, db_column, max_length=None):
        self._value = None
        self.db_column = db_column
        self.max_length = max_length
        if max_length is None:
            raise ValueError('you must specify max_length for CharField')


    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        if not isinstance(value,str):
            raise ValueError('value must str')
        if len(value) > self.max_length:
            raise ValueError('value length must smaller then max_length')
        self._value = value

class ModelMetaClass(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        if name == 'BaseModel': # BaseModel本身是没有用户自定义的字段的，这里直接使用type返回一个类
            # 这个元类的基类首先会调用一次元类，但是此时BaseModel没有用户自定义的字段，所以直接返回type
            return super().__new__(cls, name, bases, attrs, **kwargs)
        fields = {}
        for key,value in attrs.items():
            if isinstance(value,Field):
                fields[key] = value
        attr_meta = attrs.get('Meta',None)
        _meta = {}
        db_table = name.lower()
        if attr_meta is not None:
            table = getattr(attr_meta,'db_table', None)
            if table is not None:
                db_table = table
        _meta['db_table'] = db_table
        attrs['_meta'] = _meta
        attrs['fields'] = fields
        del attrs['Meta'] # 已经将Meta中的属性提取出来，Meta类就可以删除了
        return super().__new__(cls, name, bases, attrs, **kwargs)

class BaseModel(metaclass=ModelMetaClass):
    def __init__(self, *args, **kwargs):
        for key,value in kwargs.items():
            setattr(self, key, value)  # 使用元类将属性提取再在创建字段类的父类的时候将属性直接绑定上去
        return super().__init__()

    def save(self):   # 在使用类的保存功能的时候，直接在父类里生成sql语句
        fields = []
        values = []
        for key,value in self.fields.items():
            db_column = value.db_column
            if db_column is None:
                db_column = key.lower()
            fields.append(db_column)
            value = getattr(self,key)
            values.append(str(value))
        sql = "insert into {table}({fields}) value({values})".format(table=self._meta['db_table'],fields=','.join(fields),values=','.join(values))
        pass

class User(BaseModel):
    name = CharField(db_column="name", max_length=20)
    age = IntegerField(db_column="age", min_value=0, max_value=100)

    class Meta:
        db_table = 'user'

if __name__ == '__main__':
    user = User()
    user.name = 'linLinStyle'
    user.age = 20
    user.save()